import store from './user'
import { getToken, setNettyToken, getNettyToken } from '@/utils/auth'
const state = {
  msg: null,
  websock: null,
  reconnectData: null,
  lockReconnect: false, // 避免重复连接，因为onerror之后会立即触发 onclose
  timeout: 500000, // 500s一次心跳检测 1000*500
  reconnect: 5000, // 断线重连时间
  timeoutObj: null,
  serverTimeoutObj: null
}

const mutations = {
  STAFF_UPDATEWEBSOCKET(state, websock) {
    state.websock = websock
  }
}

// 实现websocket的连接，需要携带参数token
const actions = {
  // 用到 ES2015 的参数解构来简化代码（特别是我们需要调用 commit 很多次的时候）
  STAFF_WEBSOCKET({ commit }) {
    // 初始化连接
    initWebSocket()
    function initWebSocket() {
      // vue打包环境
      const wsurl = process.env.VUE_APP_WS_URL + '?token=' + getToken()
      state.websock = new WebSocket(wsurl)
      commit('STAFF_UPDATEWEBSOCKET', state.websock)
      // 只有定义了onopen方法，才能继续实现接收消息，即在使用的地方调用onmessage方法。
      state.websock.onopen = websocketonopen // 连接成功
      state.websock.onmessage = websocketonmessage // 广播成功
      state.websock.onerror = websocketonerror // 连接断开，失败
      state.websock.onclose = websocketclose // 连接关闭
      console.log(state.websock)
      // state.websock.readyState = readyState // 连接关闭
    }
    function websocketonopen() {
      console.log('连接成功')
      sendKeyForToken()
      heatBeat()
    }
    function sendKeyForToken() {
      // 调用websocket的send方法，发送数据
      // content需要处理掉回车
      const token = {
        'msgType': 1,
        'token': getToken(),
        'data': ''
      }
      state.websock.send(JSON.stringify(token))
    }
    function websocketonerror() {
      console.log('连接失败')
      reconnect()
    }
    // 各种问题导致的 连接关闭
    function websocketclose(e) {
      // CloseEvent.code: code是错误码，是整数类型
      // CloseEvent.reason: reason是断开原因，是字符串
      // CloseEvent.wasClean: wasClean表示是否正常断开，是布尔值。一般异常断开时，该值为false
      console.log('websocket 断开: ', e.code, ' ' + e.reason, ' ', e.wasClean)
      console.log(e)
      // 重连
      reconnect()
    }
    // 数据接收
    function websocketonmessage(data) {
      heatBeat() // 收到消息会刷新心跳检测，如果一直收到消息，就推迟心跳发送
      const jsonObj = JSON.parse(data.data)
      if (jsonObj.msgType === 0 || jsonObj.msgType === 1) {
        setNettyToken(jsonObj.token)
      } else {
        state.msg = data.data
      }
      // 此处可根据不同的消息类型转发到不同的vuex(待校验)
    }
    // 数据发送
    // function websocketsend(data) {
    //   state.websock.send(JSON.stringify(data))
    // }
    function heatBeat() {
      if (state.websock.readyState !== 1) {
        reconnect()
        return
      }
      state.reconnectData && clearTimeout(state.reconnectData)
      state.timeoutObj && clearInterval(state.timeoutObj)
      state.timeoutObj && clearInterval(state.timeoutObj)
      state.serverTimeoutObj && clearTimeout(state.serverTimeoutObj)
      state.timeoutObj = setInterval(() => {
        state.websock.send(JSON.stringify(heatBeatToken()))
        // state.serverTimeoutObj = setTimeout(() => {
        //   console.log('如果  5秒之后我们没有收到 后台返回的心跳检测数据 断开socket，断开后会启动重连机制')
        //   // state.websock.close() // 如果  5秒之后我们没有收到 后台返回的心跳检测数据 断开socket，断开后会启动重连机制
        // }, 3000)
      }, state.timeout)
    }
    // 断线重连
    function reconnect() {
      if (state.lockReconnect) { // 这里很关键，因为连接失败之后之后会相继触发 连接关闭，不然会连接上两个 WebSocket
        return
      }
      state.lockReconnect = true
      state.timeoutObj && clearInterval(state.timeoutObj)
      state.serverTimeoutObj && clearTimeout(state.serverTimeoutObj)
      state.reconnectData && clearTimeout(state.reconnectData)
      state.timeoutObj && clearInterval(state.timeoutObj)
      state.reconnectData = setTimeout(() => {
        console.log('断线重连中。。。。')
        initWebSocket()
        state.lockReconnect = false
      }, state.reconnect)
    }
    function heatBeatToken() {
      const token = {
        'msgType': 0,
        'token': getNettyToken(),
        'data': ''
      }
      return token
    }
  }
}

// 该部分为了获取websocket的相关方法。会发现此处跟mutations 里的写法是类似的，但是，想使用return，需要将相关数据写在getters里面。
const getters = {
  STAFF_UPDATE(state) {
    return state
  }
}
export default {
  state,
  mutations,
  actions,
  getters
}
